// 解决连续点击按钮多次请求异步响应时间反馈不按预期的问题，即重复请求的问题

import type { AxiosRequestConfig, AxiosResponse } from 'axios'

/**
 * 唯一的请求，
 * 防止重复请求，判断依据是请求的method和url
 * @returns 返回两个方法，addPendingRequest添加请求，removePendingRequest移除请求
 */
export function uniqueRequsets() {
  /**
   * 请求的集合
   */
  const pendingRequests = new Map()

  /**
   * 生成请求的key
   * @param config 请求配置
   * @returns
   */
  const generatePendingKey = <T extends AxiosRequestConfig>(config: T) => {
    const { method, url } = config
    return [method, url].join('&')
  }

  /**
   * 全局请求拦截器，用于添加待处理的请求
   * @param config 请求配置
   */
  const addPendingRequest = (config: AxiosRequestConfig) => {
    // 生成请求的key
    const key = generatePendingKey(config)
    // 如果pendingRequests中已经存在该key，则获取对应的controller并abort
    if (pendingRequests.has(key)) {
      const controller = pendingRequests.get(key)
      controller.abort()
      pendingRequests.delete(key)
    }
    // 创建一个新的controller
    const controller = new AbortController()
    // 将controller的signal赋值给config
    config.signal = controller.signal
    // 将key和controller存入pendingRequests
    pendingRequests.set(key, controller)
  }

  /**
   * 移除请求拦截器，用于移除待处理的请求
   * @param config 请求配置
   */
  const removePendingRequest = (repose: AxiosResponse) => {
    const { config } = repose
    // 生成请求的key
    const key = generatePendingKey(config)
    // 如果待处理请求中存在该key，则删除该key对应的请求
    pendingRequests.has(key) && pendingRequests.delete(key)
  }

  // 返回添加和移除请求的方法
  return {
    addPendingRequest,
    removePendingRequest
  }
}
